{%- macro write_entity(entity) -%}
    {% if entity.access != Access.private or Config.include_private -%}
        {%- if entity is Namespace -%}
            {{ write_namespace(entity) }}
        {%- elif entity is Type -%}
            {{ write_type(entity) }}
        {%- elif entity is OverloadSet -%}
            {{ write_overload_set(entity) }}
        {%- elif entity is Variable -%}
            {{ write_variable(entity) }}
        {%- endif -%}
    {%- endif -%}
{%- endmacro -%}


{%- macro write_namespace(entity) -%}
    {%- for m in entity.members.values() | select("Type") | sort -%}
        {{ write_type(m) }}
    {%- endfor -%}

    {%- for m in entity.members.values() | select("OverloadSet") | sort -%}
        {{ write_overload_set(m) }}
    {%- endfor -%}

    {%- for m in entity.members.values() | select("Variable") | sort -%}
        {{ write_variable(m) }}
    {%- endfor -%}
{%- endmacro -%}


{%- macro write_type(entity) %}
{% call(segment) section(entity) %}
{%- if segment == "summary" -%}

{%- if entity is Scope -%}
{#- public members -#}
{{ simple_summary_table(
    entity.members.values()
        | select("Type")
        | selectattr("access", "eq", Access.public),
    "Types") }}
{{ function_summary_table(
    entity.members.values()
        | select("OverloadSet")
        | selectattr("access", "eq", Access.public)
        | selectattr("kind", "eq", FunctionKind.nonstatic),
    "Member Functions") }} {#- -#}
{{ function_summary_table(
    entity.members.values()
        | select("OverloadSet")
        | selectattr("access", "eq", Access.public)
        | selectattr("kind", "eq", FunctionKind.static),
    "Static Member Functions") }}
{{ simple_summary_table(
    entity.members.values()
        | select("Variable")
        | selectattr("access", "eq", Access.public)
        | rejectattr("is_static"),
    "Data Members") }}
{{ simple_summary_table(
    entity.members.values()
        | select("Variable")
        | selectattr("access", "eq", Access.public)
        | selectattr("is_static")
        | reject("in", entity.objects),
    "Static Data Members") }}
{{ function_summary_table(
    entity.members.values()
        | select("OverloadSet")
        | selectattr("access", "eq", Access.public)
        | selectattr("kind", "eq", FunctionKind.friend),
    "Friends") }}
{{ function_summary_table(
    entity.members.values()
        | select("OverloadSet")
        | selectattr("access", "eq", Access.public)
        | selectattr("kind", "eq", FunctionKind.free),
    "Related Non-member Functions") }}
{#- protected members -#}
{{ simple_summary_table(
    entity.members.values()
        | select("Type")
        | selectattr("access", "eq", Access.protected),
    "Protected Types") }} {#- -#}
{{ function_summary_table(
    entity.members.values()
        | select("OverloadSet")
        | selectattr("access", "eq", Access.protected)
        | selectattr("kind", "eq", FunctionKind.nonstatic),
    "Protected Member Functions") }} {#- -#}
{{ function_summary_table(
    entity.members.values()
        | select("OverloadSet")
        | selectattr("access", "eq", Access.protected)
        | selectattr("kind", "eq", FunctionKind.static),
    "Protected Static Member Functions") }} {#- -#}
{{ simple_summary_table(
    entity.members.values()
        | select("Variable")
        | selectattr("access", "eq", Access.protected)
        | rejectattr("is_static"),
    "Protected Data Members") }}  {#- -#}
{{ simple_summary_table(
    entity.members.values()
        | select("Variable")
        | selectattr("access", "eq", Access.protected)
        | selectattr("is_static")
        | reject("in", entity.objects),
    "Protected Static Members") }} {#- -#}
{#- private members -#}
{%- if Config.get("include_private") %}
{{ simple_summary_table(
    entity.members.values()
        | select("Type")
        | selectattr("access", "eq", Access.private),
    "Private Types") }} {#- -#}
{{ function_summary_table(
    entity.members.values()
        | select("OverloadSet")
        | selectattr("access", "eq", Access.private)
        | selectattr("kind", "eq", FunctionKind.nonetatic),
    "Private Member Functions") }} {#- -#}
{{ function_summary_table(
    entity.members.values()
        | select("OverloadSet")
        | selectattr("access", "eq", Access.private)
        | selectattr("kind", "eq", FunctionKind.static),
    "Private Static Member Functions") }} {#- -#}
{{ simple_summary_table(
    entity.members.values()
        | select("Variable")
        | selectattr("access", "eq", Access.private)
        | rejectattr("is_static"),
    "Private Data Members") }} {#- -#}
{{ simple_summary_table(
    entity.members.values()
        | select("Variable")
        | selectattr("access", "eq", Access.private)
        | selectattr("is_static")
        | reject("in", entity.objects),
    "Private Static Members") }} {#- -#}
{%- endif -%}
{%- endif -%}

{% if entity is Enum -%}
{%- call(member) summary_table(entity.objects, "Values") -%}
    |``{{ code_escape(member.name) }}``
    |{{ description(member.brief) | trim }}
{%- endcall -%}
{%- else -%}
{{ simple_summary_table(entity.objects, "Values") }}
{%- endif -%}

{%- elif segment == "members" -%}

{%- if entity is Scope -%}
{#- public member subsections #}
:leveloffset: +1

{% for member in entity.members.values()
    | select("Type")
    | selectattr("access", "eq", Access.public) -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("OverloadSet")
    | selectattr("access", "eq", Access.public)
    | selectattr("kind", "eq", FunctionKind.nonstatic) -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("OverloadSet")
    | selectattr("access", "eq", Access.public)
    | selectattr("kind", "eq", FunctionKind.static) -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("Variable")
    | selectattr("access", "eq", Access.public)
    | rejectattr("is_static") -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("Variable")
    | selectattr("access", "eq", Access.public)
    | selectattr("is_static")
    | reject("in", entity.objects) -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("OverloadSet")
    | selectattr("access", "eq", Access.public)
    | selectattr("kind", "eq", FunctionKind.friend) -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("OverloadSet")
    | selectattr("access", "eq", Access.public)
    | selectattr("kind", "eq", FunctionKind.free) -%}
{{ write_entity(member) }}
{% endfor %}
{#- protected member subsections -#}
{%- for member in entity.members.values()
    | select("Type")
    | selectattr("access", "eq", Access.protected) -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("OverloadSet")
    | selectattr("access", "eq", Access.protected)
    | selectattr("kind", "eq", FunctionKind.nonstatic) -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("OverloadSet")
    | selectattr("access", "eq", Access.protected)
    | selectattr("kind", "eq", FunctionKind.static) -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("Variable")
    | selectattr("access", "eq", Access.protected)
    | rejectattr("is_static") -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("Variable")
    | selectattr("access", "eq", Access.protected)
    | selectattr("is_static")
    | reject("in", entity.objects) -%}
{{ write_entity(member) }}
{% endfor %}
{#- private members -#}
{%- if Config.get("include_private") %}
{%- for member in entity.members.values()
    | select("Type")
    | selectattr("access", "eq", Access.private) -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("OverloadSet")
    | selectattr("access", "eq", Access.private)
    | selectattr("kind", "eq", FunctionKind.nonstatic) -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("OverloadSet")
    | selectattr("access", "eq", Access.private)
    | selectattr("kind", "eq", FunctionKind.static) -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("Variable")
    | selectattr("access", "eq", Access.private)
    | rejectattr("is_static") -%}
{{ write_entity(member) }}
{% endfor %}
{%- for member in entity.members.values()
    | select("Variable")
    | selectattr("access", "eq", Access.private)
    | selectattr("is_static")
    | reject("in", entity.objects) -%}
{{ write_entity(member) }}
{% endfor %}
{% endif -%}

:leveloffset: -1
{%- endif -%}

{%- endif -%}

{% endcall %}
{% endmacro -%}


{%- macro write_overload_set(oset) -%}
[id={{ anchor(oset[0]) }}
{%- if oset.location -%}
    ,source-location="include/{{oset.location.file}}"
{%- endif -%}
]
= ``{{ abridged_fqn(oset[0]) }}``
{{ description(oset[0].brief) }}

{{ heading("Synopsis") }}
{% if oset.location and (oset.scope is Namespace or oset.is_friend) -%}
    Defined in header {{ source_header(oset.location.file) }}.
{%- endif %}

[source,cpp,subs="+macros,+attributes"]
----
{{ overload_set_declaration(oset) }}
----

{% if oset[0].description -%}
    {{ oset_description(oset, title="Description") }}
{%- endif %}

{% if Config.get("convenience_header")
    and oset.location
    and (oset.scope is Namespace
        or (oset.kind in (FunctionKind.free, FunctionKind.friend))) -%}
Convenience header {{ source_header(Config.convenience_header) }}
{%- endif %}

{% endmacro -%}


{%- macro write_variable(entity) -%}
{%- call(segment) section(entity) %}{% endcall -%}
{%- endmacro -%}


{%- macro section(entity) %}
[id={{ anchor(entity) }}
{%- if entity.location -%}
    ,source-location="include/{{entity.location.file}}"
{%- endif -%}
]
= ``{{ abridged_fqn(entity) }}``
{{ description(entity.brief) }}

{{ heading("Synopsis") }}
{% if entity.location
    and (entity.scope is Namespace
        or (entity is Function and entity.is_friend)) -%}
    Defined in header {{ source_header(entity.location.file) }}.
{%- endif %}

[source,cpp,subs="+macros,+attributes"]
----
{{ entity_declaration(entity) }}
----

{{ caller("summary") }}

{% if entity.description -%}
    {{ description(entity.description, title="Description") }}
{%- endif %}

{% if entity.location
    and (entity.scope is Namespace
        or (entity is Function
            and entity.kind in (FunctionKind.free, FunctionKind.friend))) -%}
Convenience header {{ source_header(Config.convenience_header) }}.
{%- endif %}
{{ caller("members") }}
{% endmacro -%}


{% macro description(parts, nesting=1, title=None) -%}
{%- for part in parts -%}
{%- if loop.first and title
    and part is not Section and part is not ParameterList
    -%}
{{ heading(title) }}
{% endif -%}

{%- if part is Paragraph -%}
    {{ phrase(part) }}{{ "\n\n" }}
{%- elif part is List -%}
{{ itemised(part, nesting) }}
{%- elif part is Section -%}
{{ subsection(part) }}
{%- elif part is CodeBlock %}
[source]
----
{% for line in part -%}
{{line}}
{% endfor -%}
----
{% elif part is ParameterList -%}
{{ parameter_list(part) }}
{% elif part is Table -%}
{{ table(part) }}
{%- else -%}
{{ part.unhandled_type() }}
{%- endif -%}
{%- endfor -%}
{%- endmacro -%}


{%- macro oset_description(oset, nesting=1, title=None) -%}
{%- set ns = namespace(done_parameters=False) -%}
{%- for part in oset[0].description -%}
{%- if loop.first and title
    and part is not Section and part is not ParameterList
    -%}
{{ heading(title) }}
{% endif -%}


{%- if part is Paragraph -%}
    {{ phrase(part) }}{{ "\n\n" }}
{%- elif part is List -%}
{{ itemised(part, nesting) }}
{%- elif part is Section -%}
    {%- if part.kind == "see" -%}
        {%- if not ns.done_parameters -%}
            {%- set ns.done_parameters = true -%}
            {{ oset_all_parameter_lists(oset) }}
        {%- endif -%}
    {%- endif -%}
    {%- if not part.kind == "return" %}{{ subsection(part) }}{% endif -%}
{%- elif part is CodeBlock %}
[source]
----
{% for line in part -%}
{{line}}
{% endfor -%}
----
{% elif part is ParameterList -%}
{%- if not ns.done_parameters -%}
{%- set ns.done_parameters = true -%}
{{ oset_all_parameter_lists(oset) }}
{%- endif -%}
{%- elif part is Table -%}
{{ table(part) }}
{%- else -%}
{{ part.unhandled_type() }}
{%- endif -%}
{%- endfor -%}
{%- if not ns.done_parameters -%}
    {{ oset_all_parameter_lists(oset) }}
{%- endif -%}
{%- endmacro -%}


{%- macro oset_all_parameter_lists(oset) -%}
{%- for kind in [
    ParameterList.TemplateParameters,
    ParameterList.ReturnValues,
    ParameterList.Parameters,
    ParameterList.Exceptions] -%}
{{ oset_parameter_list(oset, kind) }}
{% endfor -%}
{%- endmacro -%}


{%- macro itemised(lst, nesting) -%}
    {%- for item in lst -%}
        {%- for mark in range(0, nesting) -%}
            {%- if lst.is_ordered -%}
                .
            {%- else -%}
                *
            {%- endif %}
        {%- endfor %} {{ description(item, nesting + 1) }}
    {%- endfor -%}
{%- endmacro -%}


{%- macro subsection(sub) -%}
{%- if sub.kind in ["note", "warning", "attention"] -%}
{{ admonition(sub) }}
{% else -%}
{{ heading("") }}
{%- if sub.title %}{{ phrase(sub.title) }}
{%- elif sub.kind -%}
    {%- if sub.kind == "see" %}See Also
    {%- elif sub.kind == "return" %}Return Value
    {%- elif sub.kind == "author" %}Author
    {%- elif sub.kind == "authors" %}Authors
    {%- elif sub.kind == "version" %}Version
    {%- elif sub.kind == "since" %}Since
    {%- elif sub.kind == "date" %}Date
    {%- elif sub.kind == "pre" %}Preconditions
    {%- elif sub.kind == "post" %}Postconditions
    {%- elif sub.kind == "copyright" %}Copyright
    {%- elif sub.kind == "invariant" %}Invariants
    {%- elif sub.kind == "remark" %}Remarks
    {%- elif sub.kind == "par" %}Paragraph
    {%- elif sub.kind == "rcs"%}RCS
    {%- else %}Unknown
    {%- endif -%}
{%- endif %}
{{ description(sub) }}
{%- endif -%}
{%- endmacro -%}


{%- macro admonition(sub) -%}
[
{%- if sub.kind == "warning" %}WARNING
{%- elif sub.kind == "note" %}NOTE
{%- elif sub.kind == "attention" %}IMPORTANT
{%- else %}{{ sub.kind.upper() }}
{%- endif -%}
]
====
{{ description(sub) }}
====
{% endmacro -%}


{%- macro table(part) -%}
{% if part.caption %}.{{ phrase(part.caption) }}{% endif %}
|===
{%- for row in part %}
{% for cell in row -%}
    a|{{ description(cell) }}
{%- endfor %}
{% endfor %}
|===
{% endmacro -%}


{%- macro parameter_list(part) -%}
{%- set ns = namespace(title="", col="") -%}
{%- if part.kind == ParameterList.Parameters -%}
    {%- set ns.title = "Parameters" -%}
    {%- set ns.col1 = "Name" -%}
    {%- set ns.col2 = "Description" -%}
{%- elif part.kind == ParameterList.TemplateParameters -%}
    {%- set ns.title = "Template Parameters" -%}
    {%- set ns.col1 = "Type" -%}
    {%- set ns.col2 = "Description" -%}
{%- elif part.kind == ParameterList.Exceptions -%}
    {%- set ns.title = "Exceptions" -%}
    {%- set ns.col1 = "Type" -%}
    {%- set ns.col2 = "Thrown On" -%}
{%- elif part.kind == ParameterList.ReturnValues -%}
    {%- set ns.title = "Return Values" -%}
    {%- set ns.col1 = "Type" -%}
    {%- set ns.col2 = "Description" -%}
{%- endif -%}
{% call(param_block) summary_table(part, ns.title, cols=[ns.col1, ns.col2]) -%}
{%- set sep = joiner(", ") -%}
|
{%- for item in param_block -%}
{{ sep() }}``
{%- if item.type %}{{ phrase(item.type) }} {% endif -%}
{{ phrase(item.name) }}``
{%- endfor %}
|{{ description(param_block.description) }}
{% endcall -%}
{%- endmacro -%}


{%- macro oset_parameter_list(oset, kind) -%}
{%- set ns = namespace(title="", col="") -%}
{%- if kind == ParameterList.Parameters -%}
    {%- set ns.title = "Parameters" -%}
    {%- set ns.col1 = "Name" -%}
    {%- set ns.col2 = "Description" -%}
    {%- set ns.duplicates = False -%}
{%- elif kind == ParameterList.TemplateParameters -%}
    {%- set ns.title = "Template Parameters" -%}
    {%- set ns.col1 = "Type" -%}
    {%- set ns.col2 = "Description" -%}
    {%- set ns.duplicates = False -%}
{%- elif kind == ParameterList.Exceptions -%}
    {%- set ns.title = "Exceptions" -%}
    {%- set ns.col1 = "Type" -%}
    {%- set ns.col2 = "Thrown On" -%}
    {%- set ns.duplicates = True -%}
{%- elif kind == ParameterList.ReturnValues -%}
    {%- set ns.title = "Return Values" -%}
    {%- set ns.col1 = "Type" -%}
    {%- set ns.col2 = "Description" -%}
    {%- set ns.duplicates = True -%}
{%- endif -%}

{%- set params = [] -%}
{%- for func in oset -%}
    {%- for part in func.description -%}
        {%- if part is ParameterList and part.kind == kind -%}
            {%- for param in part -%}
                {%- set name = param | map(attribute="name")
                    | map(attribute="text") | join -%}
                {%- set type = param | map(attribute="type")
                    | map(attribute="text") | join -%}
                {%- set names = params | map("map", attribute="name")
                    | map("map", attribute="text") | map("join") -%}
                {%- set types = params | map("map", attribute="type")
                    | map("map", attribute="text") | map("join") -%}
                {%- if ns.duplicates or (name not in names) or (type not in types) -%}
                    {%- set ___ = params.append(param) -%}
                {%- endif -%}
            {%- endfor -%}
        {%- endif -%}
    {%- endfor -%}
{%- endfor -%}

{%- if kind == ParameterList.ReturnValues -%}
{%- set ns.did_return_values = False -%}
{%- for func in oset -%}
    {%- for part in func.description -%}
        {%- if not ns.did_return_values
                and part is Section
                and part.kind == "return" -%}
            {%- set ns.did_return_values = True -%}
            {{ subsection(part) }}
        {%- endif -%}
    {%- endfor -%}
{%- endfor -%}
{%- endif -%}

{% call(param_block) summary_table(params, ns.title, cols=[ns.col1, ns.col2]) -%}
{%- set sep = joiner(", ") -%}
|
{%- for item in param_block -%}
{{ sep() }}``
{%- if item.type %}{{ phrase(item.type,in_code="line") }} {% endif -%}
{{ phrase(item.name,in_code="line") }}``
{%- endfor %}
|{{ description(param_block.description) }}
{% endcall -%}
{%- endmacro -%}


{%- macro phrase(para, in_code=False, in_link=False) -%}
{%- for part in para -%}{{ phrase_part(part, in_code=in_code, in_link=False) }}{%- endfor -%}
{%- endmacro -%}


{%- macro phrase_part(part, in_code=False, in_link=False) -%}
    {%- if part is string -%}
        {{ text_helper(part, in_code=in_code, in_link=False) }}
    {%- elif part is EmDash -%}
        --
    {%- elif part is EnDash -%}
        {{ part.text }}
    {%- elif part is Monospaced -%}
        ``{{ phrase(part, in_code="line", in_link=in_link) }}``
    {%- elif part is Emphasised -%}
        __{{ phrase(part, in_code=in_code, in_link=in_link) }}__
    {%- elif part is Strong -%}
        **{{ phrase(part, in_code=in_code, in_link=in_link) }}**
    {%- elif part is EntityRef -%}
        {%- set is_external = Config.get("external_marker")
                and (part.entity.brief | map(attribute="text") | join | trim)
                    == Config.get("external_marker") -%}
        pass:q,a,m[
        {%- if is_external -%}
            link:
            {%- for part in part.entity.description -%}
                {%- if part is Section and part.kind == Section.See -%}
                    {{ part | map(attribute="text") | join | trim }}
                {%- endif -%}
            {%- endfor -%}
        {%- else -%}
            xref:{{ link(part.entity) }}
        {%- endif -%}
        [
        {%- if in_code -%}
            {{ abridged_fqn(part.entity) }}
        {%- else -%}
            ``{{ phrase(part, in_code="line", in_link=True) }}``
        {%- endif -%}
        \]]
    {%- elif part is UrlLink -%}
        link:pass:a[{{ escape(part.url) }}][{{ phrase(part, in_code=in_code, in_link=True) }}]
    {%- elif part is Linebreak -%}{{ "\n\n" }}
    {%- elif part is Phrase -%}
        {{ phrase(part, in_code=in_code, in_link=in_link) }}
    {%- else -%}
        {{ part.unhandled_type() }}
    {%- endif -%}
{%- endmacro -%}


{%- macro link(entity) -%}
    {%- if entity is Enumerator -%}
        {{ link(entity.enum) }}
    {%- else -%}
        {{ anchor(entity) }}
    {%- endif -%}
{%- endmacro -%}


{%- macro anchor(entity) -%}
    {%- set ns = namespace(path=entity.path) -%}
    {%- if entity.fully_qualified_name.startswith(Config.default_namespace) -%}
        {%- set ns.path = ns.path[2:] -%}
    {%- endif -%}
    {{ Config.link_prefix }}
    {%- set sep = joiner("_") -%}
    {%- for segment in ns.path -%}
        {{ sep() }}{{ sanitize_path_segment(segment.name) }}
    {%- endfor -%}
    {%- if entity.scope and not entity.scope is Namespace -%}
        {%- if (entity is Function or entity is OverloadSet) and entity.is_friend -%}_fr{%- endif -%}
        {%- if (entity is Function or entity is OverloadSet) and entity.is_free -%}_fe{%- endif -%}
    {%- endif -%}
{%- endmacro -%}


{%- macro sanitize_path_segment(segment) -%}
    {{ segment.replace("[", "_lb")
              .replace("]", "_rb")
              .replace("(", "_lp")
              .replace(")", "_rp")
              .replace("<=>", "_spshp")
              .replace("operator~", "operator_bnot")
              .replace("->", "_arrow")
              .replace("=", "_eq")
              .replace("!", "_not")
              .replace("+", "_plus")
              .replace("-", "_minus")
              .replace("&", "_and")
              .replace("|", "_or")
              .replace("^", "_xor")
              .replace("*", "_star")
              .replace("/", "_slash")
              .replace("%", "_mod")
              .replace("<", "_lt")
              .replace(">", "_gt")
              .replace("~", "_dtor")
              .replace(",", "_comma")
              .replace("::", "_")
              .replace(":", "_")
              .replace(" ", "_") }}
{%- endmacro -%}


{%- macro abridged_fqn(entity) -%}
    {%- set ns = namespace(scope=entity.scope) -%}
    {%- if entity is Function
            and (entity.is_free or entity.is_friend)
            and entity.scope
            and entity.scope is not Namespace -%} {#- friend or related -#}
        {%- set ns.scope = ns.scope.scope -%}
    {%- endif -%}
    {%- set s = ns.scope.fully_qualified_name + '::' + entity.name -%}

    {%- set prefix = Config.default_namespace + "::" -%}
    {%- if s.startswith(prefix) -%}
        {{ code_escape(s[prefix | length:]) }}
    {%- else -%}
        {{ code_escape(s) }}
    {%- endif -%}
{%- endmacro -%}


{%- macro entity_declaration(entity) -%}
{{ template_parameters(entity) }}
{%- if entity is Variable -%}
{%- set sp = joiner(" ") -%}
{%- if entity.is_static %}{{ sp() }}static{% endif -%}
{%- if entity.is_constexpr %}{{ sp() }}constexpr{% endif %}
{%- if sp() %}
{% endif -%}
{{ phrase(entity.type, in_code="block") }}
{%- if entity.args %}(*{% else %} {% endif -%}
{%- endif -%}
{%- if entity is Type %}{{ entity.declarator }} {% endif -%}
{{ entity.name }}
{%- if entity is Variable and entity.args -%}
){{ phrase(entity.args, in_code="block") }}
{%- endif -%}
{%- if entity is Class -%}
{%- set ns = namespace(sep=':') -%}
{% for entry in entity.bases %}
    {%- if entry.access != Access.private or Config.include_private %}
    {{ ns.sep }} {{ entry.access }} {% set ns.sep = ',' -%}
    {%- if entry.is_virtual %}virtual {% endif -%}
    {{ phrase(entry.base, in_code="block") }}
    {%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- if entity is Enum and entity.underlying_type %}
    : {{ phrase(entity.underlying_type, in_code="block") }}
{%- endif -%}
{%- if entity is TypeAlias %} = {{ phrase(entity.aliased, in_code="block") }}{% endif -%}
{%- if entity is Variable and entity.value %} {{ phrase(entity.value, in_code="block") }}{% endif -%}
;
{%- endmacro -%}


{%- macro overload_set_declaration(oset) -%}
{%- set sep = joiner("\n") -%}
{% for func in oset -%}
{{ sep() }}{{ function_declaration(func) }}
{%- if (oset | length) > 1 %} // <{{ loop.index }}>{% endif %}
{% endfor -%}
{% endmacro -%}


{%- macro function_declaration(entity) -%}
{{ template_parameters(entity) }}
{%- set sp = joiner(" ") -%}
{%- if entity.is_explicit %}{{ sp() }}explicit{% endif -%}
{%- if entity.is_static %}{{ sp() }}static{% endif -%}
{%- if entity.is_constexpr %}{{ sp() }}constexpr{% endif %}
{%- set ret = phrase(entity.return_type, in_code="block") -%}
{%- if ret %}{{ sp() }}{{ ret }}{% endif -%}
{%- if sp() %}
{% endif -%}
{{ block_code_escape(entity.name) }}(
{%- for param in entity.parameters %}
    {{ phrase(param.type, in_code="block") }}
    {%- if param.array %} (&{% endif -%}
    {%- if param.name -%}
        {%- if not param.array %} {% endif -%}
        {{ param.name }}
    {%- endif -%}
    {%- if param.array %}) {{ phrase(param.array, in_code="block") }}{% endif -%}
    {%- if param.default_value %} = {{ phrase(param.default_value, in_code="block") }}{% endif -%}

    {%- if not loop.last %},{% endif -%}
{%- endfor -%}
)
{%- if entity.refqual or entity.is_const -%}
    {{ " " }}
    {%- if entity.is_const %}const{% endif -%}
    {%- if "lvalue" == entity.refqual %}&
    {%- elif "rvalue" == entity.refqual %}&&
    {%- endif -%}
{%- endif -%}
{%- if entity.is_noexcept and not entity.is_destructor %} noexcept
{%- if entity.noexcept_condition -%}
    ({{ entity.noexcept_condition }})
{%- endif -%}
{%- endif -%}
{%- if not entity.is_noexcept and entity.is_destructor %} noexcept(false){% endif -%}
{%- if entity.is_deleted %} = delete
{%- elif entity.is_defaulted and Config.get("show_defaulted") %} = default
{%- endif -%}
;
{%- endmacro %}


{%- macro template_parameters(entity) -%}
{%- if entity.template_parameters or entity.is_specialization -%}template<{%- endif -%}
{%- for tparam in entity.template_parameters %}
    {{ phrase(tparam.type, in_code="block") }}
    {%- if tparam.array %} (&{% endif -%}
    {%- if tparam.name -%}
        {%- if not tparam.array %} {% endif -%}
        {{ phrase_part(tparam.name, in_code="block") }}
    {%- endif -%}
    {%- if tparam.array %}) {{ phrase(tparam.array, in_code="block") }}{% endif -%}
    {%- if tparam.default_value %} = {{ phrase(tparam.default_value, in_code="block") }}{% endif -%}

{%- if loop.last -%}
>
{% else -%}
,
{%- endif -%}

{%- else -%}
{%- if entity.is_specialization -%}
>
{% endif -%}
{%- endfor %}
{%- endmacro -%}


{%- macro simple_summary_table(sequence, title) -%}
{%- call(member) summary_table(sequence | sort, title) -%}
|<<{{ link(member) }},``{{ code_escape(member.name) }}``>>
|{{ description(member.brief) | trim }}
{%- endcall -%}
{%- endmacro -%}


{%- macro function_summary_table(sequence, title) -%}
{%- call(member) summary_table(
    sequence | sort, title, cols=["Name", "Description"]) -%}
    |<<{{ link(member) }},``{{ code_escape(member.name) }}``>>
    {%- if member.is_constructor %}{nbsp}[.silver]##[constructor]##{% endif -%}
    {%- if member.is_destructor %}{nbsp}[.silver]##[destructor]##{% endif -%}
    |{{ description(member[0].brief) | trim }}
{% endcall -%}
{%- endmacro -%}



{%- macro summary_table(sequence, title, cols=["Name", "Description"], frame="all") -%}
{%- for row in sequence -%}
{% if loop.first -%}
{{ heading(title) }}
|===
{% for col in cols %}|{{col}}{% endfor %}

{% endif -%}
    {{ caller(row) }}
{% if loop.last %}
|===
{% endif %}
{%- endfor -%}
{%- endmacro -%}


{% macro heading(title) -%}
[discrete]
=== {{ escape(title) }}
{%- endmacro -%}


{%- macro source_header(path) -%}
https://github.com/boostorg/json/blob/master/include/{{path}}[<{{path}}>]
{%- endmacro -%}


{%- macro text_helper(s, in_code=False, in_link=False) -%}
    {%- if s -%}
        {%- set replacements=Config.get("replace_strings", {}) if in_code else {} -%}

        {%- set ns = namespace(s=s) -%}
        {%- if in_code -%}
            {%- set ns.s = re.sub("\\s+", " ", ns.s, re.U) -%}
            {%- if ns.s.endswith(" &") -%}
                {%- set ns.s = ns.s[:-2] + "&" -%}
            {%- elif ns.s.endswith(" *") -%}
                {%- set ns.s = ns.s[:-2] + "*" -%}
            {%- elif ns.s.endswith(" &&") -%}
                {%- set ns.s = ns.s[:-3] + "&&" -%}
            {%- elif ns.s.endswith(" &...") -%}
                {%- set ns.s = ns.s[:-5] + "&..." -%}
            {%- elif ns.s.endswith(" *...") -%}
                {%- set ns.s = ns.s[:-5] + "*..." -%}
            {%- elif ns.s.endswith(" &&...") -%}
                {%- set ns.s = ns.s[:-6] + "&&..." -%}
            {%- endif -%}
        {%- else -%}
            {%- set ns.s = s -%}
        {%- endif -%}
        {%- for src, tgt in replacements.items() -%}
            {%- set ns.s = re.sub(src, tgt,  ns.s, flags=re.U) -%}
        {%- endfor -%}
        {%- if in_code == "block" -%}
            {{ block_code_escape(ns.s) }}
        {%- elif in_code == "line" -%}
            {{ code_escape(ns.s, in_link=in_link) }}
        {%- else -%}
            {{ escape(ns.s) }}
        {%- endif -%}
    {%- else -%}
        {{ s }}
    {%- endif -%}
{%- endmacro -%}


{%- macro escape(s) -%}
{{ s.replace("++", "{pp}") }}
{%- endmacro -%}


{%- macro block_code_escape(s) -%}
{{ s }}
{%- endmacro -%}


{%- macro code_escape(s, in_link=False) -%}
{{ s.replace("<=", "++<=++")
    .replace("->", "++->++")
    .replace("]", "\\\\]" if in_link else "]")
    .replace("...", "++...++") }}
{%- endmacro -%}


{% for entity in entities.values() -%}
    {% if entity is not Namespace -%}
        {% continue %}
    {%- endif -%}
    {% if Config.get("default_namespace")
        and entity.fully_qualified_name != Config.default_namespace -%}
        {% continue %}
    {%- endif -%}

    {{ write_namespace(entity) }}
{%- endfor %}
